"""
滴答清单相关工具
提供滴答清单任务、项目、标签等管理功能
"""

from langchain_core.tools import tool
from pydantic import BaseModel, Field
from typing import Dict, Any, Optional
import logging
import sys
import os

# 添加父目录到路径以导入backend模块
sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), '..', 'app', 'backend-python'))

logger = logging.getLogger(__name__)


class DidaTaskArgs(BaseModel):
    """滴答清单任务操作参数"""
    system_user_id: int = Field(..., description="系统用户ID（固定为1000000001）")
    action: str = Field(..., description="操作类型：create_task, get_tasks, update_task, delete_task, complete_task")
    task_id: Optional[str] = Field(None, description="任务ID（更新/删除/完成操作必需）")
    title: Optional[str] = Field(None, description="任务标题（创建操作必需）")
    content: Optional[str] = Field(None, description="任务内容/描述")
    project_id: Optional[str] = Field(None, description="项目ID")


class DidaProjectArgs(BaseModel):
    """滴答清单项目操作参数"""
    system_user_id: int = Field(..., description="系统用户ID（固定为1000000001）")
    action: str = Field(..., description="操作类型：get_projects, create_project, update_project, delete_project")
    project_id: Optional[str] = Field(None, description="项目ID（更新/删除操作必需）")
    name: Optional[str] = Field(None, description="项目名称（创建操作必需）")
    color: Optional[str] = Field(None, description="项目颜色")


def _get_dida_credentials(system_user_id: int) -> Optional[Dict]:
    """
    获取用户的滴答清单凭证
    
    Args:
        system_user_id: 系统用户ID
        
    Returns:
        凭证字典，包含access_token等
    """
    try:
        from database import query, get_db_type, init_database
        
        # 确保数据库已初始化
        init_database(strict_mode=False)
        
        db_type = get_db_type()
        
        if db_type == "mysql":
            sql = """
                SELECT access_token, refresh_token, dida_username
                FROM dida_credentials 
                WHERE system_user_id = %s AND is_active = 1
                ORDER BY updated_at DESC 
                LIMIT 1
            """
        else:
            # StarRocks: 取最新记录
            sql = """
                SELECT access_token, refresh_token, dida_username
                FROM dida_credentials 
                WHERE system_user_id = %s
                ORDER BY updated_at DESC 
                LIMIT 1
            """
        
        result = query(sql, (system_user_id,))
        
        if result and len(result) > 0:
            return result[0]
        
        return None
        
    except Exception as e:
        logger.error(f"获取滴答清单凭证失败: {e}")
        return None


@tool("manage_dida_task", args_schema=DidaTaskArgs, description="管理滴答清单任务（创建、查询、更新、删除、完成）")
def manage_dida_task(
    system_user_id: int,
    action: str,
    task_id: Optional[str] = None,
    title: Optional[str] = None,
    content: Optional[str] = None,
    project_id: Optional[str] = None
) -> str:
    """
    管理滴答清单任务
    
    支持的操作：
    - create_task: 创建任务（需要title）
    - get_tasks: 获取任务列表（可选project_id过滤）
    - update_task: 更新任务（需要task_id和要更新的字段）
    - delete_task: 删除任务（需要task_id）
    - complete_task: 完成任务（需要task_id）
    
    Args:
        system_user_id: 系统用户ID
        action: 操作类型
        task_id: 任务ID
        title: 任务标题
        content: 任务内容
        project_id: 项目ID
        
    Returns:
        操作结果的JSON字符串
    """
    try:
        # 获取凭证
        credentials = _get_dida_credentials(system_user_id)
        if not credentials:
            return "❌ 未找到滴答清单绑定信息，请先在账户设置中绑定滴答清单账号"
        
        access_token = credentials["access_token"]
        
        # 导入MCP服务
        from services.dida_mcp_service import get_dida_mcp_service
        import asyncio
        
        mcp_service = get_dida_mcp_service()
        
        # 根据操作类型调用不同的MCP方法
        if action == "create_task":
            if not title:
                return "❌ 创建任务需要提供标题（title）"
            
            loop = asyncio.new_event_loop()
            asyncio.set_event_loop(loop)
            result = loop.run_until_complete(
                mcp_service.create_task(access_token, title, content or "", project_id)
            )
            loop.close()
            
            # MCP直接返回任务对象字典，不是包装在{success: true}中
            if result and isinstance(result, dict) and result.get("id"):
                task_id = result.get("id")
                task_title = result.get("title", title)
                return f"✅ 任务创建成功：{task_title}\n📌 任务ID: {task_id}"
            else:
                return f"❌ 任务创建失败：{str(result) if result else '未知错误'}"
        
        elif action == "get_tasks":
            loop = asyncio.new_event_loop()
            asyncio.set_event_loop(loop)
            result = loop.run_until_complete(
                mcp_service.get_tasks(access_token, project_id)
            )
            loop.close()
            
            # MCP直接返回任务列表，不是包装在字典中
            if result and isinstance(result, list):
                if not result:
                    return "📋 您目前没有任务"
                
                task_list = []
                for task in result:  # 显示所有任务，不截取
                    task_info = f"- {task.get('title', '未命名任务')}"
                    # 检查是否已完成
                    if task.get('status') == 2 or task.get('isCompleted'):
                        task_info = f"✅ {task_info}"
                    else:
                        task_info = f"📌 {task_info}"
                    
                    # 添加优先级和截止日期信息
                    priority = task.get('priority')
                    if priority == 5:
                        task_info += " [高优先级]"
                    elif priority == 3:
                        task_info += " [中优先级]"
                    
                    due_date = task.get('dueDate')
                    if due_date:
                        task_info += f" 📅 {due_date[:10]}"  # 只显示日期部分
                    
                    task_list.append(task_info)
                
                return f"📋 任务列表（共{len(result)}个）：\n" + "\n".join(task_list)
            else:
                return f"❌ 获取任务失败：{str(result)}"
        
        elif action == "update_task":
            if not task_id:
                return "❌ 更新任务需要提供任务ID（task_id）"
            
            update_data = {}
            if title:
                update_data["title"] = title
            if content:
                update_data["content"] = content
            if project_id:
                update_data["project_id"] = project_id
            
            if not update_data:
                return "❌ 更新任务需要至少提供一个要更新的字段"
            
            loop = asyncio.new_event_loop()
            asyncio.set_event_loop(loop)
            result = loop.run_until_complete(
                mcp_service.update_task(access_token, task_id, **update_data)
            )
            loop.close()
            
            if result and result.get("success"):
                return "✅ 任务更新成功"
            else:
                return f"❌ 任务更新失败：{result.get('message', '未知错误')}"
        
        elif action == "delete_task":
            if not task_id:
                return "❌ 删除任务需要提供任务ID（task_id）"
            
            loop = asyncio.new_event_loop()
            asyncio.set_event_loop(loop)
            result = loop.run_until_complete(
                mcp_service.delete_task(access_token, task_id)
            )
            loop.close()
            
            if result and result.get("success"):
                return "✅ 任务删除成功"
            else:
                return f"❌ 任务删除失败：{result.get('message', '未知错误')}"
        
        elif action == "complete_task":
            if not task_id:
                return "❌ 完成任务需要提供任务ID（task_id）"
            
            loop = asyncio.new_event_loop()
            asyncio.set_event_loop(loop)
            result = loop.run_until_complete(
                mcp_service.complete_task(access_token, task_id)
            )
            loop.close()
            
            if result and result.get("success"):
                return "✅ 任务已标记为完成"
            else:
                return f"❌ 标记任务完成失败：{result.get('message', '未知错误')}"
        
        else:
            return f"❌ 不支持的操作类型：{action}"
    
    except Exception as e:
        logger.error(f"管理滴答清单任务失败: {e}", exc_info=True)
        return f"❌ 操作失败：{str(e)}"


@tool("manage_dida_project", args_schema=DidaProjectArgs, description="管理滴答清单项目（查询、创建、更新、删除）")
def manage_dida_project(
    system_user_id: int,
    action: str,
    project_id: Optional[str] = None,
    name: Optional[str] = None,
    color: Optional[str] = None
) -> str:
    """
    管理滴答清单项目
    
    支持的操作：
    - get_projects: 获取项目列表
    - create_project: 创建项目（需要name）
    - update_project: 更新项目（需要project_id和要更新的字段）
    - delete_project: 删除项目（需要project_id）
    
    Args:
        system_user_id: 系统用户ID
        action: 操作类型
        project_id: 项目ID
        name: 项目名称
        color: 项目颜色
        
    Returns:
        操作结果的JSON字符串
    """
    try:
        # 获取凭证
        credentials = _get_dida_credentials(system_user_id)
        if not credentials:
            return "❌ 未找到滴答清单绑定信息，请先在账户设置中绑定滴答清单账号"
        
        access_token = credentials["access_token"]
        
        # 导入MCP服务
        from services.dida_mcp_service import get_dida_mcp_service
        import asyncio
        
        mcp_service = get_dida_mcp_service()
        
        # 根据操作类型调用不同的MCP方法
        if action == "get_projects":
            loop = asyncio.new_event_loop()
            asyncio.set_event_loop(loop)
            result = loop.run_until_complete(
                mcp_service.get_projects(access_token)
            )
            loop.close()
            
            # MCP直接返回项目列表，不是包装在字典中
            if result and isinstance(result, list):
                if not result:
                    return "📁 您目前没有项目"
                
                project_list = []
                for project in result:  # 显示所有项目，不截取
                    project_info = f"- {project.get('name', '未命名项目')} (ID: {project.get('id')})"
                    project_list.append(project_info)
                
                return f"📁 项目列表（共{len(result)}个）：\n" + "\n".join(project_list)
            else:
                return f"❌ 获取项目失败：{str(result)}"
        
        elif action == "create_project":
            if not name:
                return "❌ 创建项目需要提供名称（name）"
            
            loop = asyncio.new_event_loop()
            asyncio.set_event_loop(loop)
            result = loop.run_until_complete(
                mcp_service.create_project(access_token, name, color)
            )
            loop.close()
            
            if result and result.get("success"):
                return f"✅ 项目创建成功：{name}"
            else:
                return f"❌ 项目创建失败：{result.get('message', '未知错误')}"
        
        elif action == "update_project":
            if not project_id:
                return "❌ 更新项目需要提供项目ID（project_id）"
            
            update_data = {}
            if name:
                update_data["name"] = name
            if color:
                update_data["color"] = color
            
            if not update_data:
                return "❌ 更新项目需要至少提供一个要更新的字段"
            
            loop = asyncio.new_event_loop()
            asyncio.set_event_loop(loop)
            result = loop.run_until_complete(
                mcp_service.update_project(access_token, project_id, **update_data)
            )
            loop.close()
            
            if result and result.get("success"):
                return "✅ 项目更新成功"
            else:
                return f"❌ 项目更新失败：{result.get('message', '未知错误')}"
        
        elif action == "delete_project":
            if not project_id:
                return "❌ 删除项目需要提供项目ID（project_id）"
            
            loop = asyncio.new_event_loop()
            asyncio.set_event_loop(loop)
            result = loop.run_until_complete(
                mcp_service.delete_project(access_token, project_id)
            )
            loop.close()
            
            if result and result.get("success"):
                return "✅ 项目删除成功"
            else:
                return f"❌ 项目删除失败：{result.get('message', '未知错误')}"
        
        else:
            return f"❌ 不支持的操作类型：{action}"
    
    except Exception as e:
        logger.error(f"管理滴答清单项目失败: {e}", exc_info=True)
        return f"❌ 操作失败：{str(e)}"

